home *** CD-ROM | disk | FTP | other *** search
/ SPACE 1 / SPACE - Library 1 - Volume 1.iso / utilitys / 93 / ppaccell / axsend.c next >
Encoding:
C/C++ Source or Header  |  1987-10-12  |  7.5 KB  |  349 lines

  1. /***************************************************************************
  2.  
  3.     Packet Accelerated XModem Transfer - by Tom Zerucha
  4.     Commercial Rights Reserved
  5.     Calibration Version
  6.  
  7. ***************************************************************************/
  8. #include "osbind.h"
  9.  
  10. /* Xmodem Character Definitions */
  11. #define    SOH    0x01
  12. #define    STX    0x02
  13. #define    EOT    0x04
  14. #define    ACK    0x06
  15. #define    NAK    0x15
  16. #define    CAN    0x18
  17.  
  18. /* Iorec buffer */
  19. struct    tbuf {
  20.     char    *bufp;
  21.     int    size;
  22.     int    head;
  23.     int    tail;
  24.     int    lwm;
  25.     int    hwm;
  26.     };
  27.  
  28. char    inbuf[1024];    /* temp buffer */
  29. #define BLEN    32768L
  30. char    getbuf[BLEN];    /* file read buffer */
  31.  
  32. char    ctmp[80];    /* for data conversion */
  33.  
  34. /* the following three parameters control acceleration */
  35. int    paulen;        /* length of pause */
  36. int    pauone;        /* number of characters before 1st pause */
  37. int    paudel;        /* number of characters less in successive groups */
  38.  
  39. long    sum[ 50 ];    /* statistic buffers */
  40. int    num[ 50 ];
  41.  
  42. /*************************/
  43. decout( val , str )
  44. long    val;
  45. char    *str;
  46. {
  47. char    tmp[10];
  48. int    i;
  49.  
  50. for( i = 0 ; val ; i++ ) {
  51.     tmp[i] = ( val % 10L ) + '0';
  52.     val /= 10L;
  53.     }
  54. while( --i >= 0 )
  55.     *str++ = tmp[i];
  56. *str = 0;
  57.  
  58. }
  59.  
  60. /*************************/
  61. /* calculate xymodem crc */
  62. /*************************/
  63. calccrc( str , len )
  64. char    *str;
  65. int    len;
  66. {
  67. int    crc,i;
  68.  
  69. crc = 0;
  70. while( --len >= 0 ) {
  71.     crc = crc ^ (int)*str++ << 8;
  72.     for( i = 0 ; i < 8 ; ++i )
  73.         if( crc & 0x8000 )
  74.             crc = crc << 1 ^ 0x1021;
  75.         else
  76.             crc = crc << 1;
  77.     }
  78. return( crc );
  79. }
  80.  
  81. /******************************/
  82. /* calculate xymodem checksum */
  83. /******************************/
  84. calccks( str , len )
  85. char    *str;
  86. int    len;
  87. {
  88. int    cks;
  89.  
  90. cks = 0;
  91. while( --len >= 0 ) {
  92.     cks += *str++;
  93.     cks &= 0xff;
  94.     }
  95.  
  96. return( cks );
  97.  
  98. }
  99.  
  100. /*********************************/
  101. /* wait for character or timeout */
  102. /*********************************/
  103. serin( dly )
  104. int    dly;
  105. {
  106. int    i;
  107. for( i = 0 ; i < dly*10 ; i++ ) {
  108.     if( Bconstat(1) )
  109.         return( Bconin(1) & 0x7f );
  110.     p_pause( 100L );
  111.     }
  112. return( -1 );
  113. }
  114.  
  115. /**********************************/
  116. /* calculate and set pause values */
  117. /**********************************/
  118. setpau( pau )
  119. int    pau;
  120. {
  121. int    i,j;
  122.  
  123. paulen = pau;
  124. /* interval of pause in characters */
  125. /* 3/5 - 1200 baud, 300 baud - 3/20 , 2400 baud - 6/5 , cps/200 */
  126. paudel = paulen * 3 / 5;
  127. /* number of intervals */
  128. pauone = 133 / paudel;
  129. /* round to trianglular interval: sum of i, i = 1 to n :1,3,6,10,15,21,28 */
  130. for( i = 55, j = 10 ; i > pauone ; i -= j-- );
  131. /* compute size of first exact multiple subpacket */
  132. pauone = j * paudel;
  133. /* distribute remainder equally between packets */
  134. pauone += ( 133 - i * paudel + j - 2 ) / j;
  135. /* the j - 2 forces the last packet to be 1 larger, for checksum mode
  136.     which is 132 characters long */
  137. /* the speed savings is (128 - pauone + paudel) character times */
  138. }
  139.  
  140. /***************************/
  141. /* send file using xymodem */
  142. /***************************/
  143. main( argc , argv )
  144. int    argc;
  145. char    *argv[];
  146. {
  147. long    len;        /* length of file */
  148. int    crcflg;        /* controls 0/1 checksum/CRC */
  149. int    blklen;        /* length of current block */
  150. int    blkseq;        /* block serial number */
  151. int    errcnt;        /* error counter */
  152. char    *getptr;    /* pointer into getbuf */
  153. long    getcnt;        /* characters remaining to send in buffer */
  154. int    crc;        /* calculated CRC of block */
  155. int    handl;        /* file handle */
  156. int    bufflg;        /* last buffer (EOF) flag */
  157. int    redoflg;    /* block was NAKed */
  158. struct tbuf *aob;    /* I/O record for output - to tell when empty */
  159. int    chr;
  160. int    i;
  161. int    tstflg;
  162. int    tstmax;
  163.  
  164. int    ipau,idel;
  165.  
  166. tstflg = 0;
  167. setpau( tstflg + 18 );
  168.  
  169. tstmax = 10;
  170. for( i = 0 ; i < tstmax ; i++ )
  171.     sum[i]=0,num[i]=0;
  172.  
  173. /* set defaults */
  174. crcflg = 0;        /* auto CRC */
  175. tstflg = 0;
  176.  
  177. aob = Iorec(0) + 0x0eL;            /* get RS-232 out I/O record */
  178.  
  179. handl = Fopen( argv[1] , 0 );        /* open file */
  180. if( handl < 0 ) {
  181.     Cconws( "OPEN FAILED\r\n" );
  182.     return( -1 );
  183.     }
  184.  
  185. len = Fseek( 0L , handl , 2 );        /* get length - 2nd param in batch */
  186. Fseek( 0L , handl , 0 );
  187.  
  188. bufflg = 0;                /* read in first buffer */
  189. getcnt = Fread( handl , BLEN , getbuf );
  190. getptr = getbuf;
  191. if( getcnt < BLEN )
  192.     bufflg = 1;
  193.  
  194. while( Bconstat(1) )            /* remove extra junk */
  195.     Bconin(1);            /* line noise between eot and C */
  196.  
  197. chr = 0;                /* determine crc vs checksum */
  198. while( chr != 'C' && chr != NAK && chr != -1 )
  199.     chr = serin( 20 );
  200. if( chr == -1 ) {
  201.     Cconws( "NO START SIGNAL - SEND ABORTED\007\r\n" );
  202.     return( -1 );
  203.     }
  204.  
  205. if( !crcflg )
  206.     crcflg = ( chr == 'C' );
  207.  
  208. blkseq = 1;                /* first block number */
  209. redoflg = 0;                /* retransmit off (for NAKs) */
  210.  
  211. blklen = 128;
  212. errcnt = 10;
  213. while( --errcnt ) {
  214.  
  215. sttim();
  216.     Bconout( 1 , SOH );
  217.     Bconout( 1 , blkseq & 0xff );
  218.     Bconout( 1 , 255 - ( blkseq & 0xff ) );
  219.  
  220.     if( !redoflg ) {        /* copy buffered file to xfer area */
  221.         for( i = 0 ; i < blklen ; i++ ) {
  222.             if( getcnt ) {
  223.                 inbuf[i] = *getptr++;
  224.                 getcnt--;
  225.                 }
  226.             else
  227.                 inbuf[i] = 0;
  228.             }
  229.         }
  230.  
  231. /* compute countdown before first pause */
  232. /*P*/    idel = 0;
  233.     ipau = -3;    /* SOH bkn bkn */
  234.     ipau += pauone - paudel * idel++;
  235.  
  236.     for( i = 0 ; i < blklen ; i++ ) {    /* send block */
  237.         Bconout( 1 , inbuf[i] );
  238.  
  239. /*P*/        if( i == ipau ) {
  240. /* compute next pause position */
  241.             ipau += pauone - paudel * idel++;
  242. /* wait until send buffer empty */
  243.             while( aob->head != aob->tail )
  244.                 ;
  245. /* pause for .1 +/- ? seconds */
  246.             p_pause( (long)(paulen*5) );
  247.             }
  248.         }
  249.  
  250.     if( crcflg & 1 ) {            /* send CRC or checksum */
  251.         crc = calccrc( inbuf , blklen );    /* calculate CRC */
  252.         Bconout( 1 , crc >> 8 );
  253.         Bconout( 1 , crc & 0xff );
  254.         }
  255.     else {
  256.         Bconout( 1 , calccks( inbuf , blklen ) );
  257.         }
  258.  
  259.     if( !getcnt && !bufflg ) {        /* get another send buffer */
  260.         getcnt = Fread( handl , BLEN , getbuf );
  261.         getptr = getbuf;
  262.         if( getcnt < BLEN )
  263.             bufflg = 1;
  264.         }
  265.  
  266.     redoflg = 1;                /* assume NAK */
  267.     while( 1 ) {                /* wait for ACK */
  268.         chr = serin( 15 );
  269.         if( aob->head != aob->tail )    /* if send not done */
  270.             continue;        /* discard noise */
  271.         if( chr == -1 ) break;        /* timeout? */
  272.         if( chr == ACK ) break;        /* reject any bad chars */
  273.         if( chr == NAK ) break;
  274.         if( chr == CAN ) break;
  275.         }
  276.  
  277. /* calculate statistics */
  278. i = 25600 / gettim();        /* compute bytes per second (128 bytes) */
  279. decout( (long)i , ctmp );    /* 200 counts per second */
  280. Cconws( "[" );
  281. Cconws( ctmp );
  282. Cconws( "]" );
  283. sum[tstflg] += i;
  284. num[tstflg]++;
  285. tstflg++;
  286. if( tstflg >= tstmax ) {
  287.     tstflg = 0;
  288.     Cconws( "\r\n" );
  289.     }
  290. setpau( tstflg + 18 );        /* change calibration */
  291.  
  292.     if( chr == ACK ) {
  293.         blkseq++;        /* advance */
  294.         redoflg = 0;        /* no retransmit */
  295.         errcnt = 10;        /* restore error count */
  296.         }
  297.  
  298.     if( chr == CAN ) break;        /* interrupt */
  299.     if( bufflg && !getcnt && !redoflg )        /* EOF */
  300.         break;
  301.  
  302.     }
  303.  
  304. Fclose( handl );
  305. if( chr == CAN ) {
  306.     Cconws( "SEND ABORTED BY RECEIVER\007\r\n" );
  307.     return( -1 );
  308.     }
  309.  
  310. chr = 0;                /* EOT and acknowledgement */
  311. while( chr != ACK && errcnt-- ) {
  312.     Bconout( 1 , EOT );
  313.     chr = serin( 3 );
  314.     }
  315.  
  316. /* Fatal Error */
  317. if( !errcnt ) {
  318.     Bconout( 1 , CAN );
  319.     Bconout( 1 , CAN );
  320.     Cconws( "SEND ABORTED - TOO MANY ERRORS\007\r\n" );
  321.     return( -1 );
  322.     }
  323.  
  324. Cconws( "SEND COMPLETED\007\r\n" );
  325.  
  326. /* print out average transfer rates */
  327. for( tstflg = 0 ; tstflg < tstmax ; tstflg++ ) {
  328.     decout( sum[tstflg] , ctmp );
  329.     Cconws( "[" );
  330.     Cconws( ctmp );
  331.     Cconws( "] " );
  332.     sum[tstflg]/=num[tstflg];
  333.     }
  334.  
  335. Cconws( "\r\n" );
  336.  
  337. for( tstflg = 0 ; tstflg < tstmax ; tstflg++ ) {
  338.     decout( sum[tstflg] , ctmp );
  339.     Cconws( "[" );
  340.     Cconws( ctmp );
  341.     Cconws( "] " );
  342.     sum[tstflg]/=num[tstflg];
  343.     }
  344.  
  345. Cconin();
  346. return( 0 );
  347.  
  348. }
  349.